package com.snow.service.meta.impl;

import com.snow.constant.ErrorConstant;
import com.snow.constant.Types;
import com.snow.dao.MetaDao;
import com.snow.dao.RelationShipDao;
import com.snow.exception.SiteException;
import com.snow.pojo.dto.MetaDto;
import com.snow.pojo.dto.cond.MetaCond;
import com.snow.pojo.model.ContentDomain;
import com.snow.pojo.model.MetaDomain;
import com.snow.pojo.model.RelationShipDomain;
import com.snow.service.content.ContentService;
import com.snow.service.meta.MetaService;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;

/**
 * @Description:
 * @author: snow
 * @Date: 2020-01-22
 **/
@Service
public class MetaServiceImpl implements MetaService {
    @Autowired
    private MetaDao metaDao;
    @Autowired
    private ContentService contentService;
    @Autowired
    private RelationShipDao relationShipDao;
    private static final Logger logger = Logger.getLogger(MetaServiceImpl.class);

    /**
     * 添加项目
     *
     * @param metaDomain
     * @return
     */
    @Override
    @Transactional
    @CacheEvict(value = {"metaCaches", "metaCache"}, allEntries = true, beforeInvocation = true)
    public int addMeta(MetaDomain metaDomain) {
        if (metaDomain == null) {
            throw new RuntimeException("Args metaDomain can not be null");
        }
        logger.debug("Add Meta in MetaService");
        int i = metaDao.addMeta(metaDomain);
        return i;
    }

    /**
     * 保存Meta
     *
     * @param name
     * @param type
     * @param mid
     * @return
     */
    @Override
    @CacheEvict(value = {"metaCaches", "metaCache"}, allEntries = true, beforeInvocation = true)
    public int saveMeta(String name, String type, Integer mid) {
        logger.debug(" Execute Save" + type + "setting method");
        int rs = 0;
        if (StringUtils.isNotBlank(name) && StringUtils.isNotBlank(type)) {
            MetaCond metaCond = new MetaCond();
            metaCond.setName(name);
            metaCond.setType(type);
            List<MetaDomain> metas = metaDao.getMetasByCond(metaCond);
            //若metas不为空那么说明更新的值已近存在没有必要更新
            if (metas == null || metas.size() == 0) {
                MetaDomain metaDomain = new MetaDomain();
                metaDomain.setType(type);
                metaDomain.setName(name);
                if (mid != null) {
                    MetaDomain meta = metaDao.getMetaById(mid);
                    //存在该mid
                    if (meta != null) {
                        metaDomain.setMid(mid);
                        rs = metaDao.updateMeta(metaDomain);
                        //每个文章更新类型
                        contentService.updateCategory(meta.getName(), name);

                    }
                }else {
                    rs = metaDao.addMeta(metaDomain);
                }
            } else {
                throw new RuntimeException("ERROR" + name + type + "Has Been Exit");
            }
        } else {
            throw new RuntimeException("Arg name or Type is null cant't be null here");
        }
        logger.debug("Exit Save Sitting Method");
        return rs;
    }

    /**
     * 批量保存meta
     *
     * @param cid
     * @param names
     * @param type
     * @return
     */

    @Override
    @Transactional
    @CacheEvict(value = {"metaCaches", "metaCache"}, allEntries = true, beforeInvocation = true)
    public void addMetas(Integer cid, String names, String type) {
        logger.debug("Enter addMetas Method");
        if (null == cid) {
            throw SiteException.withErrorCode(ErrorConstant.Commons.PARAM_IS_EMPTY);
        }
        if (StringUtils.isNotBlank(names) && StringUtils.isNotBlank(type)) {
            String[] split = names.split(",");
            for (String s : split) {
                if (StringUtils.isNotBlank(s)) {
                    this.saveOrUpdate(s, type, cid);
                }
            }
        }
        logger.debug("Exit AddMetas Method");
    }

    /**
     * 更新或保存文章的分类或标签
     *
     * @param name
     * @param type
     * @param cid
     * @return
     */

    @Override
//    @CacheEvict(value = {"metaCaches", "metaCache"}, allEntries = true, beforeInvocation = true)
    public void saveOrUpdate(String name, String type, Integer cid) {
        MetaCond metaCond = new MetaCond();
        metaCond.setType(type);
        metaCond.setName(name);
        List<MetaDomain> metas = this.getMetasByCond(metaCond);
        int mid = 0;
        if (metas.size() > 1) {
            throw new RuntimeException("Result is not noe in saveOrUpdateMeta Methos");
        } else if (metas.size() == 1 && metas.get(0) != null) {
            MetaDomain meta = metas.get(0);
            mid = meta.getMid();
        } else {
            //不存在这样的一个meta,则新增加一个
            MetaDomain metaDomain = new MetaDomain();
            metaDomain.setName(name);
            metaDomain.setType(type);
            metaDomain.setSlug(name);
            this.addMeta(metaDomain);
            mid = metaDomain.getMid();
        }
        if (mid != 0) {
            Integer count = relationShipDao.getCountById(cid, mid);
            if (count == 0) {
                /**
                 * 新标签或分类增加关联
                 */
                RelationShipDomain relationShipDomain = new RelationShipDomain();
                relationShipDomain.setCid(cid);
                logger.info("cid" + cid);
                logger.info("mid=" + mid);
                relationShipDomain.setMid(mid);
                relationShipDao.addRelationship(relationShipDomain);
            }
        }
    }

    @Override
    @Transactional
    @CacheEvict(value = {"metaCaches", "metaCache"}, allEntries = true, beforeInvocation = true)
    public void deleteMetaById(Integer mid) {
        if (mid == null) {
            throw new RuntimeException("Arg mid must not be null");
        }
        MetaDomain meta = metaDao.getMetaById(mid);
        MetaDomain metaDomain = new MetaDomain();
        if (meta != null) {
            String type = meta.getType();
            String name = meta.getName();
            metaDomain.setName(meta.getName());
            metaDomain.setType(meta.getType());
            metaDao.deleteMeta(mid);
            List<RelationShipDomain> relationships = relationShipDao.getRelationShipBymId(mid);
            if (relationships != null && relationships.size() > 0) {
                for (RelationShipDomain relationship : relationships) {
                    ContentDomain article = contentService.getArticleById(relationship.getCid());
                    if (article != null) {
                        //用来更新article的实体
                        ContentDomain temp = new ContentDomain();
                        temp.setCid(relationship.getCid());
                        if (type.equals(Types.TAG.getType())) {
                            reMeta(name, article.getTags());
                        }
                        if (type.equals(Types.CATEGORY.getType())) {
                            reMeta(name, article.getCategories());
                        }
                        contentService.updateContentById(temp);

                    }
                }
                relationShipDao.deleteRelationshipBymId(mid);
            }
        }

    }

    @Override
    @Cacheable(value = "metaCache", key = "'metaById' + #p0")
    public MetaDomain getMetaById(Integer mid) {
        if (mid == null) {
            throw SiteException.withErrorCode(ErrorConstant.Commons.PARAM_IS_EMPTY);
        }
        return metaDao.getMetaById(mid);
    }

    @Override
    @Cacheable(value = "metaCaches", key = "'metasByCond_' + #p0")
    public List<MetaDomain> getMetasByCond(MetaCond metaCond) {
        return metaDao.getMetasByCond(metaCond);
    }

    @Override
    @Cacheable(value = "metaCaches", key = "'metasFromsql'+ #p0")
    public List<MetaDto> getMetasByType(String type, String orderBy, Integer limit) {
        if (StringUtils.isBlank(type)) {
            throw SiteException.withErrorCode(ErrorConstant.Commons.PARAM_IS_EMPTY);
        }
        if (limit > 20 || limit < 0) {
            limit = 20;
        }
        HashMap<String, Object> sql = new HashMap<>();
        sql.put("type", type);
        sql.put("orderBy", orderBy);
        sql.put("limit", limit);
        List<MetaDto> metaDtos = metaDao.selectFromSql(sql);

        return metaDtos;
    }

    private String reMeta(String name, String meta) {
        String[] split = StringUtils.split(meta, ",");
        StringBuffer buffer = new StringBuffer();
        for (String s : split) {
            if (!s.equals(name)) {
                buffer.append(",").append(s);
            }

        }
        if (buffer.length() > 0) {
            return buffer.substring(1);
        }
        return "";
    }
}
